<?php

namespace App\Traits\User;

use App\Models\Role;
use App\Models\Permission;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Cache;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;

trait HasPermissions
{
    /**
     * 关联用户权限
     *
     * Date: 2018/1/25
     * @author George
     * @return BelongsToMany
     */
    public function permissions(): BelongsToMany
    {
        return $this->belongsToMany(Permission::class, 'user_permission_pivot', 'user_id', 'permission_code', 'id');
    }

    /**
     * 判断用户是否拥有指定的权限组中任意一个角色
     *
     * Date: 2018/1/25
     * @author George
     * @param array $codes
     * @return bool
     */
    public function hasPermissions(array $codes)
    {
        foreach ($codes as $code) {
            if ($this->hasPermission($code)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断用户是否拥有指定的权限
     *
     * Date: 2018/1/25
     * @author George
     * @param string $code
     * @return mixed
     */
    public function hasPermission(string $code)
    {
        $permissions = $this->getPermissionsAttribute();
        return $permissions->contains('code', $code);
    }

    /**
     * 获取用户权限
     *
     * Date: 2018/1/25
     * @author George
     * @return Collection
     */
    public function getPermissionsAttribute(): Collection
    {
        $permissions = [];

        //获取用户的角色信息编码
        $roles = $this->roles;

        //遍历角色获取对应的权限
        foreach ($roles as $role) {
        	$codes = $this->getPermissionsByRoleCode($role);
        	foreach ($codes as $code) {
				$permissions[$code->code] = $code;
			}
        }

        /**
         * 获取用户直接关联的权限
         */
        $permissionCodes = $this->permissionCodes();

        if ($permissionCodes instanceof Collection && $permissionCodes->isNotEmpty()) {
            foreach ($permissionCodes as $permission) {
                $permissions[] = Cache::rememberForever("permissions:{$permission->code}", function () use ($permission) {
                    return DB::table('permissions')
                        ->select('code', 'name', 'permissiontable_id', 'permissiontable_type')
                        ->where('code', $permission->code)->first();
                });
            }
        }
        return collect($permissions);
    }

    /**
     * 获取角色的权限
     *
     * Date: 2018/1/25
     * @author George
     * @param $role
     * @return mixed
     */
    private function getPermissionsByRoleCode($role)
    {
        $role = Role::findByCode($role->code);
        return $role->permissions;
    }

    /**
     * 获取用户的权限编码
     *
     * Date: 2018/1/25
     * @author George
     * @return Collection
     */
    public function permissionCodes(): Collection
    {
        return Cache::remember("users:{$this->id}:permissions", 10,function () {
            return DB::table('user_permission_pivot')
                ->select('perminssion_code as code')
                ->where('user_id', $this->id)->get();
        });
    }
}
